﻿using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AppFramework.Logger {
    public class LoggerSerilog : ILogger {

        public LoggerSerilog() {
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Verbose()
                .WriteTo.File($"./AppLog/{DateTime.Now:yyyyMMdd}.All.txt")
                .WriteTo.File($"./AppLog/{DateTime.Now:yyyyMMdd}.Debug.txt", Serilog.Events.LogEventLevel.Debug)
                .WriteTo.File($"./AppLog/{DateTime.Now:yyyyMMdd}.Info.txt", Serilog.Events.LogEventLevel.Information)
                .WriteTo.File($"./AppLog/{DateTime.Now:yyyyMMdd}.Warn.txt", Serilog.Events.LogEventLevel.Warning)
                .WriteTo.File($"./AppLog/{DateTime.Now:yyyyMMdd}.Error.txt", Serilog.Events.LogEventLevel.Error)
                .WriteTo.File($"./AppLog/{DateTime.Now:yyyyMMdd}.Error.txt", Serilog.Events.LogEventLevel.Fatal)
                .CreateLogger();
        }

        public event Action<LogInfo> OnLogYield;
        private readonly Queue<LogInfo> mfLogList = [];
        private int mfSyncCount = 0;
        protected void OnLogYieldRaise(LogLevel logLevel, string logText) {
            this.mfLogList.Enqueue(new LogInfo() { Level = logLevel, LogText = logText });
            if (Interlocked.Increment(ref this.mfSyncCount) > 1) {
                Interlocked.Decrement(ref this.mfSyncCount);
            } else {
                Task.Factory.StartNew(() => {
                    while (this.mfLogList.Count > 0) {
                        this.OnLogYield?.Invoke(this.mfLogList.Dequeue());
                    }
                    Interlocked.Decrement(ref this.mfSyncCount);
                });
            }
        }

        public ILogger Debug(string message) {
            this.OnLogYieldRaise(LogLevel.Debug, message);
            Log.Logger.Debug(message);            
            return this;
        }

        public ILogger Error(string message, Exception ex = null) {
            this.OnLogYieldRaise(LogLevel.Error, message);
            Log.Logger.Error(ex, message);
            return this;
        }

        public ILogger Fatal(string message, Exception ex = null) {
            this.OnLogYieldRaise(LogLevel.Fatal, message);
            Log.Logger.Fatal(ex, message);
            return this;
        }

        public ILogger Info(string message) {
            this.OnLogYieldRaise(LogLevel.Info, message);
            Log.Logger.Information(message);
            return this;
        }

        public ILogger Trace(string message) {
            this.OnLogYieldRaise(LogLevel.Trace, message);
            Log.Logger.Verbose(message);
            return this;
        }

        public ILogger Warn(string message) {
            this.OnLogYieldRaise(LogLevel.Warn, message);
            Log.Logger.Warning(message);
            return this;
        }

    }
}
